home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 October
/
CHIP Turkiye Ekim 2000.iso
/
prog
/
naps
/
04
/
setup.exe
/
Gnucleus
/
GnuHash.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-24
|
5KB
|
202 lines
/********************************************************************************
Gnucleus - A node application for the Gnutella network
Copyright (C) 2000 John Marshall
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For support, questions, comments, etc...
E-Mail:
swabby@c0re.net
Address:
21 Cadogan Way
Nashua, NH, USA 03062
********************************************************************************/
// GnuHash.cpp: implementation of the CGnuHash class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Gnucleus.h"
#include "GnucleusDoc.h"
#include "ViewSearch.h"
#include "GnuTransfer.h"
#include "GnuSock.h"
#include "GnuHash.h"
#include "GnuControl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGnuHash::CGnuHash()
{
GnuComm = NULL;
HashEntries = 0;
Current = 0;
Old = 1;
for(int i = 0; i < HASH_SIZE; i++)
{
Table[0][i] = NULL;
Table[1][i] = NULL;
}
}
CGnuHash::CGnuHash(CGnuControl *pGnuComm)
{
GnuComm = pGnuComm;
HashEntries = 0;
Current = 0;
Old = 1;
for(int i = 0; i < HASH_SIZE; i++)
{
Table[0][i] = NULL;
Table[1][i] = NULL;
}
}
CGnuHash::~CGnuHash()
{
for(int i = 0; i < HASH_SIZE; i++)
{
if(Table[0][i] != NULL)
delete Table[0][i];
if(Table[1][i] != NULL)
delete Table[1][i];
}
}
void CGnuHash::Insert(GUID *Guid, CGnuSock *Origin)
{
DWORD key = CreateKey(Guid);
int attempts = MAX_REHASH;
while(Table[Current][key] != NULL && attempts--)
key = (key + REHASH_VALUE) % HASH_SIZE;
// Check to see if table is full
if(Table[Current][key] != NULL)
{
// time to clean out the old and switch
ClearTable(Old);
if (Current == 0)
{
Current = 1;
Old = 0;
}
else
{
Current = 0;
Old = 1;
}
key = CreateKey(Guid); // don't need to rehash, we know it's empty
}
Table[Current][key] = new key_data;
Table[Current][key]->Guid = *Guid;
Table[Current][key]->Origin = Origin;
HashEntries++;
}
key_data* CGnuHash::FindValue(GUID *Guid)
{
DWORD key = CreateKey(Guid);
int attempts = MAX_REHASH; // HASH_SIZE, I dont want to search forever
// search the current table
while(attempts--)
{
if(Table[Current][key] != NULL && CompareGuid(&Table[Current][key]->Guid, Guid))
return Table[Current][key];
key = (key + REHASH_VALUE) % HASH_SIZE;
}
// try the old table
attempts = MAX_REHASH;
while(attempts--)
{
if(Table[Old][key] != NULL && CompareGuid(&Table[Old][key]->Guid, Guid))
return Table[Old][key];
key = (key + REHASH_VALUE) % HASH_SIZE;
}
// not found ...
return NULL;
}
bool CGnuHash::CheckEmpty(int which)
{
for(int i = 0; i < HASH_SIZE; i++)
if(Table[which][i] != NULL)
return 0;
return 1;
}
DWORD CGnuHash::CreateKey(GUID *Guid)
{
byte *GuidRaw = (byte *) Guid;
// XOR every 4 bytes together ...
DWORD key = (GuidRaw[0] ^ GuidRaw[4] ^ GuidRaw[8] ^ GuidRaw[12]) +
256 * (GuidRaw[1] ^ GuidRaw[5] ^ GuidRaw[9] ^ GuidRaw[13]) +
256 * 256 * (GuidRaw[2] ^ GuidRaw[6] ^ GuidRaw[10] ^ GuidRaw[14]) +
256 * 256 * 256 * (GuidRaw[3] ^ GuidRaw[7] ^ GuidRaw[11] ^ GuidRaw[15]);
// and modulo it down to size
key %= HASH_SIZE;
return key;
}
bool CGnuHash::CompareGuid(GUID *Guid1, GUID *Guid2)
{
byte *GuidRaw1 = (byte *) Guid1;
byte *GuidRaw2 = (byte *) Guid2;
for(int i = 0; i < 16; i++)
if(GuidRaw1[i] != GuidRaw2[i])
return 0;
return 1;
}
void CGnuHash::ClearTable(int which)
{
for(int i = 0; i < HASH_SIZE; i++)
if(Table[which][i] != NULL)
{
delete Table[which][i];
Table[which][i] = NULL;
}
HashEntries = 0;
}